package com.cn.shiro.zy.shiro.realm;

import com.cn.shiro.zy.shiro.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Value;

import java.util.Objects;

/**
 * @author zhangyi
 * @date 2018/12/11 22:42
 */
public class MyRealm extends AuthorizingRealm {

    @Value("${zy.salt}")
    private String salt;

    /**
     * 动态生成盐,验证的时候，从数据库中获取此数据在和密码对比
     */
//    private String saltDym = new SecureRandomNumberGenerator().nextBytes().toHex();
    private String saltDym = "ae1d252d6cd1e34c96ad19f45d3a4188";

    /**
     * 自定义授权逻辑
     * Authorization
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        User principal = null;
        Object obj = SecurityUtils.getSubject().getPrincipal();
        if(Objects.isNull(obj)){
            return null;
        }else{
            //获取当前操作者信息
            principal = (User) obj;
        }
        System.out.println("当前操作者信息： "+principal.getUserName()+"---"+principal.getPassword());
        //给资源授权
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //加上授权字符串(当前用户已经授权)
        simpleAuthorizationInfo.addStringPermission("user:add");
        //获取用户信息
        User userSession = (User)SecurityUtils.getSubject().getSession().getAttribute("userSession");
        System.out.println(userSession.getPassword()+"===="+userSession.getUserName());
        return simpleAuthorizationInfo;
    }

    /**
     * 自定义认证的逻辑
     *  判断用户名和密码
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken auth = (UsernamePasswordToken) authenticationToken;
        User user = null;
        System.out.println("处理用户登录逻辑");
        char[] password = auth.getPassword();
        System.out.println("get password： "+new String((char[])authenticationToken.getCredentials()));
        // get user auccount
        String username = auth.getUsername();
        //select user info by username

        //we make ex for this:
        if("admin".equals(username)){
             user = new User(1,"admin","ef91e91ab331300458070df6facf63ec");
        }
        if(!"admin".equals(username) && Objects.isNull(user)){
//            返回null 会抛出 UnknownAccountException
            return null;
        }
        //此中方式无法将用户信息存储，后期无法抢转
//        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(password,"123",getName());
        //用户登录验证
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                user,
                user.getPassword(),
//                ByteSource.Util.bytes(salt),
                ByteSource.Util.bytes(username+new String(password)+saltDym),
                //realm name
                getName());
        //add shiro session
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("userSession",user);
        session.setAttribute("userSessionId",user.getId());
        //successful
        return simpleAuthenticationInfo;
    }

    /**
     * 自定密码判断
     *
     * @param pass
     * @return
     */
    private boolean isPassWord(String password,char[] pass){
        if(pass.length != password.length()){
            return false;
        }
        char[] chars = password.toCharArray();
        for(int i = 0; i < pass.length; i++){
            if(chars[i] != pass[i]){
                return false;
            }
        }
        return true;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }
}
